package logic;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import presentation.MainScreen;

public class SimonSays {
	private List<Integer> players;
	private int playerIndex = 0;
	private Integer currentPlayer;
	private int gestureIndex = 0;
	
	//Used to know if the player need to reproduce a new gesture or an old gesture
	private boolean isNewGesture = false;
	
	private Pattern pattern;
	private Set<Action> actions;
	private Action currentAction;
	private boolean running;
	MainScreen Ps;
	
	private void extendPattern() {
		/* Extend the current pattern by randomly selecting an action */
		Random random = new Random();
		int index = random.nextInt(actions.size());
		pattern.extend((Action) actions.toArray()[index]);
	}
	
	public int getGestureIndex(){
		return gestureIndex;
	}
	
	public boolean getNewGesture(){
		return isNewGesture;
	}
	
	private void setNewGesture(){
		isNewGesture = ((pattern.size() - 1) == gestureIndex);
	}
	
	private void removePlayer(Integer player) {
		players.remove(player);
	}
	
	private void nextAction() {
		currentAction = pattern.getNextAction();
	}
	
	/**
	 * Requires a Collection of allowed Actions as an argument. These are the only actions
	 * that can be contained in a Pattern.
	 * 
	 * @param c
	 */
	public SimonSays(Collection<Action> c) {
		/* Initialise by adding all allowed actions to the game */
		this.players = new ArrayList<Integer>();
		this.pattern = new Pattern();
		this.actions = new HashSet<Action>();
		for (Action a : c) {
			actions.add(a);
		}
	}
	
	/**
	 * Returns the identifying number of the current player.
	 * 
	 * @return
	 */
	public int getCurrentPlayer() {
		return currentPlayer;
	}

	/**
	 * Changes the turn to the next player and returns his/her identifiying number.
	 * 
	 * @return
	 */
	public int nextPlayer() {
		playerIndex++;
		if (playerIndex < players.size()) {
			return currentPlayer = players.get(playerIndex);
		} else {
			playerIndex = 0;
			return currentPlayer = players.get(playerIndex);
		}
	}
	
	/**
	 * Returns the current action.
	 * 
	 * @return
	 */
	public Action getCurrentAction() {
		return currentAction;
	}
	
	/**
	 * 
	 * Input an action and process the results. If it matches the current action
	 * in the current pattern, return the next player. If it doesn't, that
	 * player is no longer part of the game. In that case, the return value will
	 * be: -1 if a player was removed and there are still players in the game.
	 * -2 if there are no more players (the game is finished).
	 * 
	 * @param action
	 * @return
	 */
	public int inputAction(Action action) {
		if (currentAction.equals(action)) {
			System.out.println("CORRECT ACTION");
			/* Action was correct but the pattern is not completed */
			if (pattern.hasMore()) {
				gestureIndex = gestureIndex + 1;
				System.out.println("gestureIndex: " +  gestureIndex + "patroonsize: " + pattern.size());
				setNewGesture();
				nextAction();
				return currentPlayer;
			/* Action was correct and pattern is completed */
			} else {
				pattern.resetToStart();
				isNewGesture = false;
				gestureIndex = 0;
				extendPattern();
				nextAction();
				System.out.println(currentPlayer);
				try {
					TimeUnit.SECONDS.sleep(2);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				return nextPlayer();
			}
			/* Action was incorrect and there are still players in the game */
		} else if (players.size() > 1) {
			System.out.println("INCORRECT ACTION");
			removePlayer(currentPlayer);
			gameLost(currentPlayer);
			nextPlayer();
			pattern.resetToStart();
			isNewGesture = false;
			gestureIndex = 0;
			nextAction();
			return -1;
			/* Action was incorrect and there are no more players left */
		} else {
			System.out.println("STOPPING GAME");
			gameLost(currentPlayer);
			stopGame();
			return -2;
		}
	}
	
	/**
	 * 
	 * Setup all variables. Requires a non-negative, non-zero argument.
	 * 
	 * @param playerCount
	 * @throws Exception
	 */
	public void startGame(int playerCount) throws Exception {
		if (playerCount < 1) {
			throw new Exception("Invalid playerCount" + playerCount);
		} else {
			running = true;
			for (int i = 0; i < playerCount; i++) {
				System.out.println(i);
				players.add(new Integer(i));
			}
			currentPlayer = players.get(playerIndex);
			isNewGesture = true;
			extendPattern();
			currentAction = pattern.getNextAction();
		}
	}

	/**
	 * 
	 * Cleanup: remove everything set by startGame().
	 * 
	 */
	public void stopGame() {
		running = false;
		this.currentAction = null;
		this.currentPlayer = null;
		this.pattern = null;
		this.players = null;		
	}

	/**
	 * Returns whether the game is running or not.
	 * 
	 * @return
	 */
	public boolean isRunning() {
		return this.running;
	}

	public void gameLost(int player) {
		System.out.println("Player " + (player+1) + " has lost the game");
		Ps.popupLost(player);
	}
	
}













